package org.zn.note.mybatis.setting;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

import static org.zn.note.mybatis.util.MyBatisUtils.DEBUG;

/**
 * MyBatis 插件
 * <p>
 * MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下，MyBatis 允许使用插件来拦截的方法调用包括：
 * <p>
 * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
 * ParameterHandler (getParameterObject, setParameters)
 * ResultSetHandler (handleResultSets, handleOutputParameters)
 * StatementHandler (prepare, parameterize, batch, update, query)
 * 这些类中方法的细节可以通过查看每个方法的签名来发现，或者直接查看 MyBatis 发行包中的源代码。
 * 如果你想做的不仅仅是监控方法的调用，那么你最好相当了解要重写的方法的行为。
 * 因为在试图修改或重写已有方法的行为时，很可能会破坏 MyBatis 的核心模块。
 * 这些都是更底层的类和方法，所以使用插件的时候要特别当心。
 * <p>
 * 1、实现 {@link Interceptor}
 * 2、指定要拦截的方法的签名
 * 3、配置XML <plugins>
 */
@Intercepts({@Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MyPlugin implements Interceptor {

    private Properties properties = new Properties();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // implement pre processing if need
        if (DEBUG)
            System.out.printf("This is ExamplePlugin.intercept before\n");
        Object returnObject = invocation.proceed();
        // implement post processing if need
        if (DEBUG)
            System.out.printf("This is ExamplePlugin.intercept after\n");
        return returnObject;
    }

    @Override
    public void setProperties(Properties properties) {
        if (DEBUG)
            System.out.printf("This is ExamplePlugin.setProperties: %s\n", properties);
        this.properties = properties;
    }
}
